package com.readfeed.app;

import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import android.app.ActionBar;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AbsListView.MultiChoiceModeListener;

import com.readfeed.app.adapter.ChannelsListAdapter;
import com.readfeed.app.data.FeedsAdapter;
import com.readfeed.app.fragment.AddChannelDialogFragment;
import com.readfeed.app.fragment.DialogEventsListener;
import com.readfeed.app.fragment.ErrorDialogFragment;
import com.readfeed.app.fragment.ProgressDialogFragment;
import com.readfeed.app.model.Channel;
import com.readfeed.app.utils.Utilities;

public class ChannelsListActivity extends Activity implements DialogEventsListener {

	public static final String CHANNEL_ID_EXTRA = "id";
	public static final String CHANNEL_TITLE_EXTRA = "title";
	public static final String CHANNEL_URI_EXTRA = "url";
	public static final String CHANNEL_UPDATE_EXTRA = "update";
	private static final String CHANNEL_ADDED_MESSAGE ="Channel added";
	private static final String CHANNEL_DELETED_MESSAGE = "Channel deleted";
	
	private static final String ADD_CHANNEL_DIALOG_TAG = "add_channel";
	
	private boolean mMustParseFeed;
	private String mChannelTitle;
	private long mCategoryId;
	private ChannelParser mChannelParser;
	private FeedsAdapter mFeedAdapter;
	private ChannelsListAdapter mListAdapter;	
	private ListView mListView;
	private FragmentManager mFragmentManager;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_channels_list);		
		setupActionBar();		
		mFeedAdapter = new FeedsAdapter(this);
		mFeedAdapter.open();
		
		mCategoryId = getIntent().getExtras().getLong(CategoriesListActivity.CATEGORY_ID_EXTRA);
		mFragmentManager = getFragmentManager();
		mListView = (ListView)findViewById(R.id.channels_list_view);
		this.configureListView();	
	}
	
	@Override
	protected void onResume() {		
		super.onResume();
		this.fillData();
	}
	
	private void configureListView(){
		mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
		mListView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
			private int selectedCount;
			
			@Override
			public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
				List<Channel> ch = mListAdapter.getSelectedChannels();
				if (ch.size() != 0) {				
					switch (item.getItemId()) {                
		                case R.id.action_delete:
		                    selectedCount = 0;		                    
		                    deleteChannels(ch);
		                    mListAdapter.removeSelectedChannels();
		                    mListAdapter.clearSelection();
		                    
		                    mode.finish();
					}
				} else {
					Toast.makeText(ChannelsListActivity.this, Utilities.NO_ITEMS_SELECTED_MESSAGE, Toast.LENGTH_SHORT).show();
				}
				
				return false;
			}										

			@Override
			public boolean onCreateActionMode(ActionMode mode, Menu menu) {
				selectedCount = 0;
				MenuInflater inflater = getMenuInflater();
				inflater.inflate(R.menu.context_menu, menu);
				return true;
			}

			@Override
			public void onDestroyActionMode(ActionMode mode) {
				mListAdapter.clearSelection();
				
			}

			@Override
			public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
				return false;			
			}

			@Override
			public void onItemCheckedStateChanged(ActionMode mode,
					int position, long id, boolean checked) {			
				 if (checked) {
					 selectedCount++;
                     mListAdapter.setNewSelection(position, checked);                    
                 } else {
                	 selectedCount--;
                     mListAdapter.removeSelection(position);                 
                 }
				 
                 mode.setTitle(selectedCount + " items selected");
			}
		});
		
		mListView.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position,
					long id) {
				Channel clickedItem = mListAdapter.getChannelByPosition(position);
				long channelId = clickedItem.getId();
				String channelTitle = clickedItem.getTitle();
				String channelUri = clickedItem.getUri();
				long channelUpdate = clickedItem.getLastUpdate();
				
				Intent intent = new Intent(ChannelsListActivity.this, FeedsListActivity.class);
				intent.putExtra(CHANNEL_ID_EXTRA, channelId);
				intent.putExtra(CHANNEL_TITLE_EXTRA, channelTitle);
				intent.putExtra(CHANNEL_URI_EXTRA, channelUri);
				intent.putExtra(CHANNEL_UPDATE_EXTRA, channelUpdate);
				
				startActivity(intent);				
			}
		});
	}
	
	@Override
	protected void onDestroy() {
		super.onDestroy();
	}
	
	private void fillData(){
		FillDataTask fillDataTask = new FillDataTask();
		fillDataTask.execute();
	}
	
	@SuppressWarnings("unchecked")
	private void deleteChannels(List<Channel> channels){
		DeleteChannelTask deleteTask = new DeleteChannelTask();
		deleteTask.execute(channels);
	}

	private void setupActionBar() {
		ActionBar actionBar = getActionBar();
		actionBar.setDisplayHomeAsUpEnabled(true);
		String title = getIntent().getExtras().getString(CategoriesListActivity.CATEGORY_TITLE_EXTRA);
		
		actionBar.setTitle(title);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {		
		getMenuInflater().inflate(R.menu.channels_list, menu);		
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:			
			NavUtils.navigateUpFromSameTask(this);
			break;
			
		case R.id.action_addchannel:
			AddChannelDialogFragment addChannelDialog = AddChannelDialogFragment.newInstance();
			addChannelDialog.show(mFragmentManager, ADD_CHANNEL_DIALOG_TAG);
			break;
			
		case R.id.channels_action_settings:
			Intent prefIntent = new Intent(ChannelsListActivity.this, PreferencesActivity.class);
			startActivity(prefIntent);			
			break;								
		}
		
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onDialogPositiveClick(DialogFragment dialog) {		
			mMustParseFeed = true;
			Dialog currentDialog = dialog.getDialog();			
			
			EditText titleView = (EditText)currentDialog.findViewById(R.id.channel_title);
			EditText urlView = (EditText)currentDialog.findViewById(R.id.channel_uri);
			
			mChannelTitle = titleView.getText().toString();
			boolean isValidTitle = true;
			if (mChannelTitle != null && !mChannelTitle.equals("")) {
				isValidTitle = Utilities.validateTitle(mChannelTitle);
			}
			
			String url = urlView.getText().toString();			
			try{
				URL testUrl = new URL(url);
			} catch(MalformedURLException mue){
				mMustParseFeed = false;
				ErrorDialogFragment errorDialog = ErrorDialogFragment.newInstance(R.string.malformed_url_error);
				errorDialog.show(mFragmentManager, Utilities.ERROR_DIALOG_TAG);
			}
			
			ConnectionDetector detector = new ConnectionDetector(ChannelsListActivity.this);
			if (detector.isConnectingToInternet()) {						
				if (mMustParseFeed) {
					if (isValidTitle) {
						ParseFeedTask parseTask = new ParseFeedTask();
						parseTask.execute(url, mChannelTitle);
					} else {
						ErrorDialogFragment errorDialog = ErrorDialogFragment.newInstance(
								R.string.title_validation_error);
						errorDialog.show(mFragmentManager, Utilities.ERROR_DIALOG_TAG);
					}				
				}
			} else {
				ErrorDialogFragment errorDialog = ErrorDialogFragment.newInstance(R.string.no_connection_error);
				errorDialog.show(mFragmentManager, Utilities.ERROR_DIALOG_TAG);
			}
		}	

	@Override
	public void onDialogNegativeClick(DialogFragment dialog) {
		dialog.dismiss();		
	}	
	
	private class FillDataTask extends AsyncTask<Void, Void, List<Channel>>{
		private Exception ex = null;
		
		@Override
		protected List<Channel> doInBackground(Void... params) {
			List<Channel> channels = new ArrayList<Channel>();
			try {
				channels = mFeedAdapter.getFullChannelsByCategory(mCategoryId);
			} catch (ParseException e) {
				this.ex = e;
			}
					
			return channels;
		}
		
		@Override
		protected void onPostExecute(List<Channel> result) {
			if (ex != null) {
				ErrorDialogFragment errorDialog = ErrorDialogFragment.newInstance(R.string.parsing_error);
				errorDialog.show(mFragmentManager, Utilities.ERROR_DIALOG_TAG);
			} else {
				mListAdapter = new ChannelsListAdapter(ChannelsListActivity.this, R.layout.channel_row, result);
				mListView.setAdapter(mListAdapter);
			}
		}
	}
	
	private class ParseFeedTask extends AsyncTask<String, Void, Channel>{
		private Exception ex = null;
		
		@Override
		protected void onPreExecute() {
			ProgressDialogFragment progressDialog = ProgressDialogFragment.newInstance(
					R.string.progress_dialog_loading);
			progressDialog.show(mFragmentManager, Utilities.PROGRESS_DIALOG_TAG);
		}
		
		@Override
		protected Channel doInBackground(String... params) {
			mChannelParser = new ChannelParser();			
			Channel result = null;
			try{
				URL url = new URL(params[0]);
				String title = params[1];
				
				result = mChannelParser.handleChannel(url);
				result.setUri(params[0]);
				if (title != null && !title.equals("")) {
					result.setTitle(title);
				}

				mFeedAdapter.createChannel(result, mCategoryId);
			} catch(Exception e){
				this.ex = e;
			}
			
			return result;			
		}
		
		@Override
		protected void onPostExecute(Channel result) {
			if (ex != null) {
				((ProgressDialogFragment)mFragmentManager.findFragmentByTag(Utilities.PROGRESS_DIALOG_TAG)).dismiss();
				ErrorDialogFragment errorDialog = ErrorDialogFragment.newInstance(R.string.parsing_error);
				errorDialog.show(mFragmentManager, Utilities.ERROR_DIALOG_TAG);
			} else{			
				//TODO toast text to constant
				ProgressDialogFragment fr = ((ProgressDialogFragment)getFragmentManager().
						findFragmentByTag(Utilities.PROGRESS_DIALOG_TAG));
				if (fr != null) {
					fr.dismiss();
				}
				
				mListAdapter.add(result);				
				Toast.makeText(ChannelsListActivity.this, CHANNEL_ADDED_MESSAGE, Toast.LENGTH_LONG).show();
			}
		}
	}
	
	private class DeleteChannelTask extends AsyncTask<List<Channel>,Void, Void>{

		@Override
		protected void onPreExecute() {
			ProgressDialogFragment progressDialog = ProgressDialogFragment.newInstance(
					R.string.progress_dialog_loading);
			progressDialog.show(getFragmentManager(), Utilities.PROGRESS_DIALOG_TAG);;
		}
		
		@Override
		protected Void doInBackground(List<Channel>... channels) {
			List<Channel> channelsList = channels[0];
			mFeedAdapter.deleteChannels(channelsList);			
			return null;
		}
		
		@Override
		protected void onPostExecute(Void result) {
			//TODO toast text to constant
			ProgressDialogFragment fr = ((ProgressDialogFragment)getFragmentManager().findFragmentByTag(Utilities.PROGRESS_DIALOG_TAG));
			if (fr != null) {
				fr.dismiss();
			}
						
			Toast.makeText(ChannelsListActivity.this, CHANNEL_DELETED_MESSAGE, Toast.LENGTH_LONG).show();
		}
	}
}
